/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fourbox.client;

import fourbox.Metafile;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author hartono
 */
public class ClientDownloadHandler implements Runnable {

    String workingPath;
    public static final int TIME_OUT = 5000;
    long lastTime;
    long currTime;
    List queue;
    Socket socket;

    public ClientDownloadHandler(Socket socket, List queue, String workingPath) {
        this.socket = socket;
        this.queue = queue;
        this.workingPath = workingPath;
    }

    @Override
    public void run() {
        System.out.println("Client Downloader : Thread  is started ");
        Metafile headQueue = null;
        boolean connectionOn = true;
        synchronized (queue) {
            if (queue.size() == 0) {
                try {
                    socket.close();
                    System.out.println("Client Downloader : queue is empty, no file to download");
                } catch (IOException ex) {
                    Logger.getLogger(ClientDownloadHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
                return;
            } else {
                // queue not empty
                System.out.println("Client Downloader : There are " + queue.size() + " file to be downloaded");
                headQueue = (Metafile) queue.get(0);
                try {

                    DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
                    ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());

                    System.out.println("Client Downloader : Thread start receiving input stream");

                    currTime = System.currentTimeMillis();
                    lastTime = System.currentTimeMillis();
                    while (connectionOn) {
                        currTime = System.currentTimeMillis();
                        if (inputStream.available() != 0) {

                            lastTime = System.currentTimeMillis();
                            System.out.println("Client Downloader : Try to receiving file ");

                            try {
                                int index= inputStream.readInt();                                
                                Metafile metafile = (Metafile) inputStream.readObject();
                                System.out.println("Client Downloader : Receiving Metafile -> " + metafile);
                                if (metafile.equals(headQueue)) {
                                    // validate the metafile.. if same as head of queue
                                    if (metafile.isFile) {
                                        // is file
                                        File fo = Metafile.createFileFromMetafileClient(workingPath, metafile); // file output path                                        
                                        if (!fo.exists()) {
                                            fo.createNewFile();
                                        } else {
                                            fo.delete();
                                            fo.createNewFile();
                                        }

                                        FileOutputStream fos = new FileOutputStream(fo);
                                        byte[] blockData = new byte[1];
                                        while (inputStream.available() != 0) {
                                            int len = inputStream.read(blockData);
                                            fos.write(blockData);
                                        }
                                        fos.close();
                                        System.out.println("Client Downloader : File "+ headQueue+" received");

                                        // cek sum dulu
                                        if (true) {
                                            // if success, 

                                            // sent ack
                                            outputStream.writeInt(1);
                                            outputStream.write(1);
                                            outputStream.flush();
                                            System.out.println("Client Downloader : Sent ACK");
                                            try {
                                                Thread.sleep(100);
                                            } catch (Exception e2) {
                                            }

                                            queue.remove(0);
                                            if (queue.size() == 0) {
                                                connectionOn = false;
                                            } else if (queue.size() > 0) {
                                                headQueue = (Metafile) queue.get(0);
                                            }

                                        } else {
                                            outputStream.writeInt(1);
                                            outputStream.write(0);
                                            outputStream.flush();
                                            try {
                                                Thread.sleep(100);
                                            } catch (Exception e2) {
                                            }
                                            System.out.println("Client Downloader : File not received well, Send NAK");
                                        }
                                         lastTime = System.currentTimeMillis();
                                    } else {
                                        // is folder                                        
                                        File fo = Metafile.createFileFromMetafileClient(workingPath, metafile);
                                        if (!fo.exists()) {
                                            fo.mkdirs();
                                        }
                                        outputStream.writeInt(1);
                                        outputStream.write(1);
                                        outputStream.flush();
                                        System.out.println("Client Downloader : Folder created, Send ACK");
                                        // if true
                                        queue.remove(0);
                                        if (queue.size() == 0) {
                                            try {
                                                Thread.sleep(100);
                                                connectionOn = false;
                                            } catch (Exception e2) {
                                                connectionOn = false;
                                            }
                                        } else if (queue.size() > 0) {
                                            headQueue = (Metafile) queue.get(0);
                                        }
                                        lastTime = System.currentTimeMillis();
                                        
                                    }// check tipe file
                                } else {
                                    // sent nak
                                    outputStream.writeInt(1);
                                    outputStream.write(0);
                                    outputStream.flush();
                                    System.out.println("Client Downloader : Not valid metafile it should be : " + metafile);
                                    System.out.println("Client Downloader : But " + headQueue + " found, send NAK");
                                    try {
                                        Thread.sleep(100);
                                        connectionOn = false;
                                    } catch (Exception e2) {
                                        connectionOn = false;
                                    }
                                    lastTime = System.currentTimeMillis();
                                }
                            } catch (Exception e) {
                                try {
                                    outputStream.writeInt(1);
                                    outputStream.write(0);
                                    outputStream.flush();
                                    try {
                                        Thread.sleep(100);
                                        connectionOn = false;
                                    } catch (Exception e2) {
                                        connectionOn = false;
                                    }
                                    System.out.println("Client Downloader : Msg BAD, send NAK");
                                    lastTime = System.currentTimeMillis();
                                } catch (Exception e2) {
                                    System.out.println("Client Downloader : Disconnected with client");
                                    connectionOn = false;
                                }
                            }
                        } else {
                            // check time out
                            if (currTime - lastTime > TIME_OUT) {
                                System.out.println("Client Downloader : Thread TIME OUT");
                                connectionOn = false;
                            }
                        }

//                        try {
//                            Thread.sleep(100);
//                        } catch (InterruptedException ex) {
//                        }

                    } // connection on
                    inputStream.close();
                    outputStream.close();
                    socket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }// queue not empty
        }

        System.out.println("Client Downloader : Thread is closed");
    }
}
